/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hos_ahmedadeltito.photoeditorsdk;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.*;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Size;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;


public class BrushDrawingView extends Component implements Component.TouchEventListener {

    private float brushSize = 10;
    private float brushEraserSize = 100;

    private Path drawPath;
    private Paint drawPaint;
    private Paint canvasPaint;

    private Canvas drawCanvas;
    private PixelMap canvasBitmap;
    private boolean brushDrawMode;

    private OnPhotoEditorSDKListener onPhotoEditorSDKListener;

    private BlendMode darken;

    public BrushDrawingView(Context context) {
        this(context, null);
    }

    public BrushDrawingView(Context context, AttrSet attrSet) {
        this(context, attrSet, "");

    }

    public BrushDrawingView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        setupBrushDrawing();
        addDrawTask(drawTask);
        //TODO 控件宽高需要和图片大小持平,用这种页面宽高不间断刷新有BUG
//        setLayoutRefreshedListener(this::onRefreshed);
    }

    void setupBrushDrawing() {
        drawPath = new Path();
        drawPaint = new Paint();
        drawPaint.setAntiAlias(true);
        drawPaint.setDither(true);
        drawPaint.setColor(Color.BLACK);
        drawPaint.setStyle(Paint.Style.STROKE_STYLE);
        drawPaint.setStrokeJoin(Paint.Join.ROUND_JOIN);
        drawPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
        drawPaint.setStrokeWidth(brushSize);
        darken = BlendMode.DARKEN;
        drawPaint.setBlendMode(darken);
        canvasPaint = new Paint();
        canvasPaint.setDither(false);
        this.setVisibility(Component.HIDE);
        setTouchEventListener(this);
    }

    private void refreshBrushDrawing() {
        brushDrawMode = true;
        drawPaint.setAntiAlias(true);
        drawPaint.setDither(true);
        drawPaint.setStyle(Paint.Style.STROKE_STYLE);
        drawPaint.setStrokeJoin(Paint.Join.ROUND_JOIN);
        drawPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
        drawPaint.setStrokeWidth(brushSize);
        drawPaint.setBlendMode(darken);
    }

    void brushEraser() {
        drawPaint.setStrokeWidth(brushEraserSize);
        BlendMode clear = BlendMode.CLEAR;
        drawPaint.setBlendMode(clear);
    }

    void setBrushDrawingMode(boolean brushDrawMode) {
        this.brushDrawMode = brushDrawMode;
        if (brushDrawMode) {
            this.setVisibility(Component.VISIBLE);
            refreshBrushDrawing();
        }
    }

    void setBrushSize(float size) {
        brushSize = size;
        refreshBrushDrawing();
    }

    void setBrushColor(Color color) {
        drawPaint.setColor(color);
        refreshBrushDrawing();
    }

    void setBrushEraserSize(float brushEraserSize) {
        this.brushEraserSize = brushEraserSize;
    }

    void setBrushEraserColor(Color color) {
        drawPaint.setColor(color);
        refreshBrushDrawing();
    }

    float getEraserSize() {
        return brushEraserSize;
    }

    float getBrushSize() {
        return brushSize;
    }

    Color getBrushColor() {
        return drawPaint.getColor();
    }

    void clearAll() {
        if (drawCanvas != null) {
            drawCanvas.drawColor(0, Canvas.PorterDuffMode.CLEAR);
            invalidate();
        }
    }

    public void setOnPhotoEditorSDKListener(OnPhotoEditorSDKListener onPhotoEditorSDKListener) {
        this.onPhotoEditorSDKListener = onPhotoEditorSDKListener;
    }


    public void onRefreshed(Component component) {
        onSizeChanged(component.getWidth(), component.getHeight());
    }

    public void setImage(PixelMap pixelMap) {
        refreshBrushDrawing();
        onSizeChanged(pixelMap.getImageInfo().size.width, pixelMap.getImageInfo().size.height);
    }

    private void onSizeChanged(int w, int h) {
        PixelMap.InitializationOptions opt = new PixelMap.InitializationOptions();
        opt.pixelFormat = PixelFormat.ARGB_8888;
        opt.size = new Size(w, h);
        canvasBitmap = PixelMap.create(opt);
        Texture texture = new Texture(canvasBitmap);
        drawCanvas = new Canvas(texture);

    }

    private final DrawTask drawTask = new DrawTask() {
        @Override
        public void onDraw(Component component, Canvas canvas) {
            canvasPaint.setDither(false);
            PixelMapHolder mPixelMapHolder = new PixelMapHolder(canvasBitmap);

            canvas.drawPixelMapHolder(new PixelMapHolder(canvasBitmap), 0, 0, canvasPaint);
            canvas.drawPath(drawPath, drawPaint);
        }
    };

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        if (brushDrawMode) {
            MmiPoint point = touchEvent.getPointerScreenPosition(0);
            int[] locationOnScreen = getLocationOnScreen();
            float touchX = point.getX() - locationOnScreen[0];
            float touchY = point.getY() - locationOnScreen[1];
            switch (touchEvent.getAction()) {
                case TouchEvent.PRIMARY_POINT_DOWN:

                    drawPath.moveTo(touchX, touchY);
                    if (onPhotoEditorSDKListener != null)
                        onPhotoEditorSDKListener.onStartViewChangeListener(ViewType.BRUSH_DRAWING);
                    break;
                case TouchEvent.POINT_MOVE:
                    drawPath.lineTo(touchX, touchY);
                    break;
                case TouchEvent.PRIMARY_POINT_UP:
                    drawCanvas.drawPath(drawPath, drawPaint);
                    drawPath.reset();
//                    drawPath.rewind();
                    if (onPhotoEditorSDKListener != null)
                        onPhotoEditorSDKListener.onStopViewChangeListener(ViewType.BRUSH_DRAWING);
                    break;
                default:
                    return false;
            }
            invalidate();
            return true;
        } else {
            return false;
        }
    }
}
